package com.zhuiyun.project.api.joingroup.service.impl;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zhuiyun.project.api.appuser.entity.User;
import com.zhuiyun.project.api.appuser.service.AppUserService;
import com.zhuiyun.project.api.check.model.CheckModel;
import com.zhuiyun.project.api.check.service.CheckService;
import com.zhuiyun.project.api.group.entity.Group;
import com.zhuiyun.project.api.group.service.GroupService;
import com.zhuiyun.project.api.groupmessage.service.GroupMessageService;
import com.zhuiyun.project.api.joingroup.entity.JoinGroup;
import com.zhuiyun.project.api.joingroup.mapper.JoinGroupMapper;
import com.zhuiyun.project.api.joingroup.model.JoinGroupModel;
import com.zhuiyun.project.api.joingroup.service.JoinGroupService;
import com.zhuiyun.project.api.message.config.MessageType;
import com.zhuiyun.project.api.messagelist.entity.MessageList;
import com.zhuiyun.project.api.messagelist.mapper.MessageListMapper;
import com.zhuiyun.project.api.messagelist.model.MessageListModel;
import com.zhuiyun.project.api.messagelist.service.MessageListService;
import com.zhuiyun.project.common.errorCode.EmErrorCode;
import com.zhuiyun.project.common.response.CommonResult;
import com.zhuiyun.project.websocket.SocketServer;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.websocket.Session;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.zhuiyun.project.websocket.SocketServer.groupMap;
import static com.zhuiyun.project.websocket.SocketServer.sessionMap;

/**
 * @ClassName JoinGroupServiceImpl
 * @Description TODO
 * @Author kdj
 * @Date 2023/7/24 17:17
 **/
@Service
public class JoinGroupServiceImpl implements JoinGroupService {
    @Autowired
    private JoinGroupMapper groupMapper;
    @Autowired
    private GroupService groupService;

    @Autowired
    private GroupMessageService groupMessageService;
    @Autowired
    private AppUserService appUserService;
    @Autowired
    private SocketServer socketServer;
    @Autowired
    private MessageListService messageListService;
    @Autowired
    private CheckService checkService;

    @Autowired
    private MessageListMapper messageListMapper;

    /**
     * @param userId
     * @param groupId
     * @Author kdj
     * @Description 获取joinGroup
     * @Date 2023/7/24 19:44
     * @Return boolean
     */
    @Override
    public boolean addSysUserInJoinGroup(int userId, int groupId, String joinCause, int type) {
        //根据groupId获取最后一条消息和最后一条消息

//        Map groupChatLast = groupMessageService.getGroupChatLast(userId, groupId, type);
        JoinGroup joinGroup = new JoinGroup();
        joinGroup.setUserId(userId);
        joinGroup.setGroupId(groupId);
        joinGroup.setIsMuted(0);

        joinGroup.setUserType(type);
//        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        Date date = null;
//        try {
//            date = formatter.parse((String) groupChatLast.get("createTime"));
//            System.out.println(date);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        joinGroup.setLastMessageTime(date);
//        joinGroup.setLastMessageContent((String) groupChatLast.get("content"));
        joinGroup.setDelFlag(0);
        joinGroup.setUnReadNum(0);
        joinGroup.setCreateTime(new Date());
        joinGroup.setUpdateTime(new Date());
        //判断type的类型
        if (MessageType.socketSysNum == type) {
            //添加时间
            joinGroup.setJoinTime(new Date());
            //直接通过
            joinGroup.setJoinStatus(1);
        } else {
            //还得等管理员  审核
            joinGroup.setJoinStatus(0);
            joinGroup.setJoinCause(joinCause);
        }
        return groupMapper.insertSelective(joinGroup) > 0 ? true : false;
    }

    /**
     * @param userId
     * @param groupId
     * @param type
     * @Author kdj
     * @Description 根据userId，groupId，type 获取JoinGroup数据
     * @Date 2023/7/24 21:26
     * @Return com.zhuiyun.project.api.joingroup.entity.JoinGroup
     */
    @Override
    public JoinGroup getGroupData(int userId, int groupId, int type) {
        return groupMapper.getGroupData(userId, groupId, type);
    }

    /**
     * @param id
     * @param type
     * @Author kdj
     * @Description 根据用户id和类型获取用户加入的群聊id
     * @Date 2023/7/25 16:12
     * @Return java.util.List<java.lang.Integer>
     */
    @Override
    public List<Integer> queryGroupsByUserId(int id, int type) {
        return groupMapper.queryGroupsByUserId(id, type);
    }

    /**
     * @param id
     * @param type
     * @Author kdj
     * @Description 根据用户id和类型获取用户加入的群聊id
     * @Date 2023/7/26 9:43
     * @Return java.util.List<com.zhuiyun.project.api.group.entity.Group>
     */
    @Override
    public List<Map> queryGroupsDataByUserId(int id, int type) {
        return groupMapper.queryGroupsDataByUserId(id, type);
    }

    /**
     * @param joinGroupModel
     * @Author kdj
     * @Description 申请加入群聊 系统人员
     * @Date 2023/7/25 21:40
     * @Return com.zhuiyun.project.common.response.CommonResult
     */
    @Override
    public CommonResult toJoinGroupSys(JoinGroupModel joinGroupModel) {
        boolean b = addSysUserInJoinGroup(joinGroupModel.getUserId(), joinGroupModel.getGroupId(), null, MessageType.socketSysNum);
        if (b) {
            return CommonResult.ok();
        }
        return CommonResult.error(EmErrorCode.SAVE_ERROR);
    }

    /**
     * @Author 小江
     * @Description //TODO 根据群号查询 群成员
     * @Date 8:46 2023/7/27
     **/
    @Override
    public CommonResult setByGroupId(int groupId) {

        List<Map> joinGroups = groupMapper.setByGroupId(groupId);

        List<Map> collect = joinGroups.stream().map(map -> {
            //判断map是否为空值
            if (ObjectUtil.isEmpty(map)) {
                map = new HashMap();
                //该用户不在群里
                map.put("status", false);
                return map;
            }
            //该用户在群里

            //入群时间
            DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            LocalDateTime localDateTime = (LocalDateTime) map.get("joinTime");
            String joinTime = localDateTime.format(fmt);
            //判断是否禁言
            map.put("joinTime", joinTime);
            Date now = new Date();
            //入群时间
            map.put("isTop", 0);
            if (map.get("mushinTime") != null) {
                LocalDateTime mushinTime = (LocalDateTime) map.get("mushinTime");
                Date muteTime = Date.from(mushinTime.toInstant(ZoneOffset.ofHours(8)));
                if (now.getTime() > muteTime.getTime()) {
                    map.put("isTop", 0);
                } else if (now.getTime() < muteTime.getTime()) {
                    map.put("isTop", 1);
                }
            }

            map.put("status", true);
            return map;
        }).collect(Collectors.toList());

        return CommonResult.ok(collect);
    }

    /**
     * @param groupId
     * @param userId
     * @Author kdj
     * @Description 根据群号查询群成员
     * @Date 2023/8/10 18:44
     * @Return com.zhuiyun.project.common.response.CommonResult
     */
    @Override
    public CommonResult setLinkGroupId(int groupId, int userId) {
        Map map = groupMapper.setLinkGroupId(groupId, userId);
        //判断map是否为空值
        if (ObjectUtil.isEmpty(map)) {
            map = new HashMap();
            //该用户不在群里
            map.put("status", false);
            return CommonResult.ok(map);
        }
        //入群时间
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDateTime localDateTime = (LocalDateTime) map.get("joinTime");
        String joinTime = localDateTime.format(fmt);

        map.put("joinTime", joinTime);
        //该用户在群里
        //判断是否禁言
        Date now = new Date();
        //入群时间
        map.put("isTop", 0);
        if (map.get("mushinTime") != null) {
            LocalDateTime mushinTime = (LocalDateTime) map.get("mushinTime");
            Date muteTime = Date.from(mushinTime.toInstant(ZoneOffset.ofHours(8)));
            if (now.getTime() > muteTime.getTime()) {
                map.put("isTop", 0);
            } else if (now.getTime() < muteTime.getTime()) {
                map.put("isTop", 1);
            }
        }


        map.put("status", true);
        return CommonResult.ok(map);
    }


    @Override
    public CommonResult stormFriend(Integer fromId, Integer groupId) {

        List<JoinGroup> list = groupMapper.setByGroupIdse(fromId, groupId);
        return CommonResult.ok(list);

    }

    /**
     * @Author 小江
     * @Description //TODO 判断是否禁言
     * @Date 11:33 2023/7/31
     **/
    @Override
    public boolean stormroup(int userId, int groupId) {

//        Example example = new Example(Check.class);
//        //按照修改时间倒叙
//        example.createCriteria().andEqualTo("toUserId", toUserId).andEqualTo("delFlag", 0);
////        example.setOrderByClause("update_time DESC");
//        List<Check> checks = checkMapper.selectByExample(example);
        JoinGroup joinGroup = new JoinGroup();
        joinGroup.setUserId(userId);
        JoinGroup joinGroups = groupMapper.selectOne(joinGroup);

//        if (joinGroups.getDelFlag() == 0) {
//            Date now = new Date();
//            Date muteTime = joinGroups.getMushinUser();
//            if (muteTime == null) {
//                return true;
//            } else if (now.getTime() > muteTime.getTime()) {
//                return true;
//            } else if (now.getTime() < muteTime.getTime()) {
//                return false;
//            }
//        }
        return true;
    }


    /**
     * @Author 小江
     * @Description 添加禁言时间
     * @Date 9:56 2023/7/28
     **/
    @Override
    public int joinins(MessageListModel model) {
        Integer fromId = model.getFromId();
        Integer toId = model.getToId();
        String mushinTimeLong = model.getMushinTimeLong();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date now = new Date();

        MessageList messageList = new MessageList();

        int i = 0;
        // 添加
        int items = Integer.parseInt(mushinTimeLong);
        int time = items * 1000;//30分钟
        Date date = new Date(now.getTime() + time);//30分钟后的时间
        Example example = new Example(MessageList.class);
        example.createCriteria().andEqualTo("toId", toId)
                .andEqualTo("fromId", fromId).andEqualTo("type", 2);
        messageList.setMushinTime(date);
        i = messageListMapper.updateByExampleSelective(messageList, example);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type", "storm_person");
        jsonObject.put("groupId", fromId);
        jsonObject.put("date", sdf.format(date));

        jsonObject.put("isStorm", true);
        new SocketServer().sendMessageById("app_" + toId, jsonObject.toString());
        return i;
    }


    /**
     * @Author 小江
     * @Description //TODO 踢出群聊
     * @Date 19:46 2023/7/27
     **/
    @Override
    public int groupDel(Integer fromId, Integer toId, String groupName, String value) {
        //对joinGroup中的成员删除
        groupMapper.delGroup(toId, fromId);
        //逻辑删除 对messagelist列表
        int i1 = messageListMapper.masslistDel(toId, fromId);
        //从websocket中的map删除
        if (!groupMap.containsKey(fromId.toString())) {
            //如果不存在的就不管websocket
            return 0;
        }
        //获取该群的session集合
        Set<Session> room = groupMap.get(fromId.toString());
        //根据id获取该用户session
        String key = "app_" + toId;
        if (!sessionMap.containsKey(key)) {
            //如果不存在的就不管websocket
            return 0;
        }
        //根据sessionMap获取session
        Session session = sessionMap.get(key);
        room.remove(session);
        groupMap.put(fromId.toString(), room);
        //发送websocket消息
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type", "del_noreason");
        jsonObject.put("delFlag", 1);
        jsonObject.put("fromId", fromId);
        jsonObject.put("toId", toId);
        jsonObject.put("isStorms", true);
        //系统消息对象
        String uuid = toId + UUID.randomUUID().toString();
        String checkReason = "您已被管理员从" + groupName + "移除。原因是：" + value;
        JSONObject jo1 = new JSONObject();
        jo1.put("checkReason", checkReason);
        jo1.put("toUserId", toId);
        jo1.put("checkType", 4);
        jo1.put("type", "check-person");
        //将时间转换String'
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(new Date());
        jo1.put("createTime", format);
        jo1.put("uuid", uuid);
        jo1.put("isRead", 0);
        CheckModel checkModel = JSONUtil.toBean(jo1, CheckModel.class);
        checkService.insertCheck(checkModel);
        new SocketServer().sendMessageById(key, jsonObject.toString());

        new SocketServer().sendMessageById(key, jo1.toString());
        return i1;
    }

    @Override
    public int plainDel(Integer userId, Integer groupId) {
        int i = groupMapper.delGroup(userId, groupId);//永久删除
        int i1 = messageListMapper.masslistDels(userId, groupId);
        Set<String> set = groupMap.keySet();
//        groupMap.remove(groupId);
        System.out.println("踢出群聊" + groupMap);
        String string = groupId.toString();
        groupMap.remove(string);
        System.out.println(groupMap);
        JSONObject jsonObject = new JSONObject();

        jsonObject.put("type", "del_roof");
        jsonObject.put("delFlag", 1);
        jsonObject.put("groupId", groupId);
        jsonObject.put("userId", userId);
        jsonObject.put("isStormesgo", true);
        new SocketServer().sendMessageById("app_" + userId, jsonObject.toString());
        return i;
    }

    /**
     * @Author 小江
     * @Description //TODO 踢出群聊
     * @Date 8:47 2023/8/2
     **/
    @Override
    public boolean delNoreason(Integer fromId, String groupId) {
        //删除标识
        if (groupMapper.delNoreason(fromId, groupId) < 1) {
            return false;
        }
        return true;
    }


    /**
     * @Author 小江
     * @Description //TODO 解除禁言时间
     * @Date 10:54 2023/7/29
     **/
    @Override
    public int relievetime(MessageListModel model) {
        //成员
        Integer toId = model.getToId();
        //发送人
        Integer fromId = model.getFromId();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        MessageList messageList = new MessageList();

        Example example = new Example(MessageList.class);
        example.createCriteria().andEqualTo("toId", toId)
                .andEqualTo("fromId", fromId);
        Date date = new Date();
        messageList.setMushinTime(date);
        int i = messageListMapper.updateByExampleSelective(messageList, example);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type", "storm_person");
        jsonObject.put("groupId", fromId);
        jsonObject.put("date", sdf.format(date));
        jsonObject.put("isStorm", true);
        new SocketServer().sendMessageById("app_" + toId, jsonObject.toString());
        return i;
    }

    /**
     * @param joinGroupModel
     * @Author kdj
     * @Description 申请加入群聊 app
     * @Date 2023/7/27 15:27
     * @Return com.zhuiyun.project.common.response.CommonResult
     */
    @Override
    public CommonResult toJoinGroupApp(JoinGroupModel joinGroupModel) {
        //判断之前是否申请过
        JoinGroup joinGroup = getGroupData(joinGroupModel.getUserId(), joinGroupModel.getGroupId(), MessageType.socketAppNum);
        if (joinGroup == null) {
            boolean b = addSysUserInJoinGroup(joinGroupModel.getUserId(), joinGroupModel.getGroupId(), joinGroupModel.getJoinCause(), MessageType.socketAppNum);
            if (b) {
                return CommonResult.ok();
            }
        } else {
            //修改修改时间
            joinGroup.setUpdateTime(new Date());
            joinGroup.setDelFlag(0);
            joinGroup.setJoinStatus(0);
            joinGroup.setJoinCause(joinGroupModel.getJoinCause());
            joinGroup.setJoinTime(null);
            int i = groupMapper.updateByPrimaryKeySelective(joinGroup);
            if (i > 0) {
                return CommonResult.ok();
            }
        }
        return CommonResult.error(EmErrorCode.SAVE_ERROR);
    }

    /**
     * @param userId
     * @Author kdj
     * @Description 获取我创建群的入群审核
     * @Date 2023/7/27 16:23
     * @Return com.zhuiyun.project.common.response.CommonResult
     */
    @Override
    public CommonResult getJoinGroupAudits(int userId) {
        //根据群id获取入群审核
        List<JoinGroupModel> joinGroupAudits = groupMapper.getJoinGroupAuditsByCreateUserId(userId);

        List<Map<String, Object>> collect = joinGroupAudits.stream().map(joinGroupAuditsById -> {
            //创建集合对象
            Map<String, Object> map = new HashMap<>();
            Integer joinStatus = joinGroupAuditsById.getJoinStatus();
            Integer delFlag = joinGroupAuditsById.getDelFlag();

            if (joinStatus == 1 && delFlag == 0) { //通过
                map.put("type", 1);

            } else if (joinStatus == 1 && delFlag == 1) { //删除
                map.put("type", 2);

            } else if (joinStatus == 0 && delFlag == 0) {//入群审核中
                map.put("type", 3);
            } else {
                map.put("type", 4);//拒绝
            }
            map.put("groupImgId", joinGroupAuditsById.getGroupImgId());
            map.put("groupName", joinGroupAuditsById.getGroupName());
            map.put("content", joinGroupAuditsById.getJoinCause());
            map.put("groupId", joinGroupAuditsById.getGroupId());
            map.put("userId", joinGroupAuditsById.getUserId());
            map.put("userName", joinGroupAuditsById.getUserName());
            map.put("userImgId", joinGroupAuditsById.getUserImgId());
            map.put("updateTime", joinGroupAuditsById.getUpdateTime());
            return map;
        }).collect(Collectors.toList());
        //添加到集合当中
        return CommonResult.ok(collect);
    }

    /**
     * @param groupId
     * @Author kdj
     * @Description 根据群id获取入群申请
     * @Date 2023/7/27 16:41
     * @Return com.zhuiyun.project.api.joingroup.entity.JoinGroup
     */
    @Override
    public List<JoinGroupModel> getJoinGroupAuditsById(int groupId) {
        return groupMapper.getJoinGroupAuditsById(groupId);
    }

    /**
     * @param createUserId
     * @Author kdj
     * @Description 获取未处理的未读数
     * @Date 2023/7/27 20:34
     * @Return com.zhuiyun.project.common.response.CommonResult
     */
    @Override
    public CommonResult getUnReadJoinGroup(int createUserId) {
        return CommonResult.ok(groupMapper.getUnReadJoinGroup(createUserId));
    }

    /**
     * @param userId
     * @Author kdj
     * @Description 获取我申请过的入群审核
     * @Date 2023/7/28 10:28
     * @Return java.util.List<java.util.Map>
     */
    @Override
    public List<Map> getJoinGroupAuditByMe(int userId) {
        List<JoinGroup> groups = groupMapper.getJoinGroupAuditByMe(userId);
        List<Map> collect = groups.stream().map(group -> {
            Map map = new HashMap<>();
            //根据groups获取头像和群名称
            //根据群id获取群名称和群img
            Group groupByGroupId = groupService.getGroupByGroupId(group.getGroupId());
            String groupName = groupByGroupId.getGroupName();
            Integer groupImgId = groupByGroupId.getGroupImgId();
            Integer joinStatus = group.getJoinStatus();
            Integer delFlag = group.getDelFlag();

            if (joinStatus == 1 && delFlag == 0) { //通过
                map.put("type", 1);

            } else if (joinStatus == 1 && delFlag == 1) { //删除
                map.put("type", 2);

            } else if (joinStatus == 0 && delFlag == 0) {//入群审核中
                map.put("type", 3);
            } else {
                map.put("type", 4);//拒绝
            }
            map.put("groupImgId", groupImgId);
            map.put("groupName", groupName);
            map.put("content", group.getJoinCause());
            map.put("groupId", group.getGroupId());
            return map;
        }).collect(Collectors.toList());

        return collect;
    }

    /**
     * @param joinGroupModel
     * @Author kdj
     * @Description 审核拒绝加入群聊
     * @Date 2023/7/28 10:59
     * @Return com.zhuiyun.project.common.response.CommonResult
     */
    @Override
    public CommonResult toNoJoin(JoinGroupModel joinGroupModel) {
        //修改时间
        //修改delFlag和joinstatus
        int i = groupMapper.toNoJoin(joinGroupModel);
        if (i > 0) {
            //给好友未读消息增加
            appUserService.addFriendNewNum(joinGroupModel.getUserId());
            //向websocket发消息
            Map map = new HashMap<>();
            map.put("type", "add_friend");
            socketServer.sendMessageById(MessageType.socketApp + "_" + joinGroupModel.getUserId(), JSONUtil.toJsonStr(map));
            return CommonResult.ok();
        }
        return CommonResult.error(EmErrorCode.UPDATE_ERROR);
    }

    /**
     * @param joinGroupModel
     * @Author kdj
     * @Description 审核同意加入群聊
     * @Date 2023/7/28 15:36
     * @Return com.zhuiyun.project.common.response.CommonResult
     */
    @Override
    @Transactional
    public CommonResult toOkJoin(JoinGroupModel joinGroupModel) {
        JoinGroup joinGroup = new JoinGroup();
        BeanUtils.copyProperties(joinGroupModel, joinGroup);
        //修改时间
        //修改delFlag和joinstatus
        int i = groupMapper.toOkJoin(joinGroupModel);
        if (i > 0) {
            //给好友未读消息增加
            appUserService.addFriendNewNum(joinGroupModel.getUserId());
            //添加 messageList
            MessageList groupMsgList = messageListService.createGroupMsgList(joinGroup);
            if (groupMsgList == null) {
                return CommonResult.error(EmErrorCode.UPDATE_ERROR);
            }
            //向websocket发消息
            Map map = new HashMap<>();
            map.put("type", "join_group_success");
            map.put("chatType", 2);
            Integer groupId = joinGroupModel.getGroupId();
            map.put("fromId", groupId);
            //发送websocket消息
            socketServer.sendMessageById(MessageType.socketApp + "_" + joinGroupModel.getUserId(), JSONUtil.toJsonStr(map));
            //将该session加入到该group中
            //获取该id的session
            //该账号没登录
            if (!sessionMap.containsKey("app_" + joinGroupModel.getUserId())) {
                return CommonResult.ok();
            }
            //该账号登录中。。。
            Session session = sessionMap.get("app_" + joinGroupModel.getUserId());
            if (!groupMap.containsKey(groupId.toString())) {
                // 创建房间不存在时，创建房间
                Set<Session> room = new HashSet<Session>();
                // 添加用户
                room.add(session);
                groupMap.put(groupId.toString(), room);
            } else {

                // 房间已存在，直接添加用户到相应的房间
                Set<Session> room = groupMap.get(groupId.toString());
                //判断该session是不是在该map中
                int t = 0;
                for (Session session1 : room) {
                    if (session1.getId().equals(session.getId())) {
                        t = 1;
                    }
                }
                if (t == 0) {
                    room.add(session);
                    groupMap.put(groupId.toString(), room);
                }

            }
            return CommonResult.ok();
        }
        return CommonResult.error(EmErrorCode.UPDATE_ERROR);
    }


}
